# sprites

: sprite-wall
	0b11111111
	0b11000011
	0b10100101
	0b10011001
	0b10011001
	0b10100101
	0b11000011
	0b11111111
: sprite-dirt
	0b10101010
	0b01010101
	0b10101010
	0b01010101
	0b10101010
	0b01010101
	0b10101010
	0b01010101
: sprite-boulder
	0b00111100
	0b01111110
	0b11111111
	0b11111111
	0b11111111
	0b11111111
	0b01111110
	0b00111100
: sprite-diamond
	0b00011000
	0b00100100
	0b01000010
	0b11111111
	0b11111111
	0b01000010
	0b00100100
	0b00011000
: sprite-player
	0b00111000
	0b00111000
	0b00111000
	0b00010000
	0b01111100
	0b00010000
	0b00101000
	0b01000100
: sprite-exit
	0b01111110
	0b01000010
	0b01000010
	0b01001110
	0b01001110
	0b01000010
	0b01000010
	0b01111110

: sprite-title
	0b11111111 0b10000000
	0b10000000 0b01100000
	0b10000000 0b00010000
	0b10000000 0b00001000
	0b10000000 0b00000100
	0b10000000 0b00000100
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000100
	0b10000000 0b00000100
	0b10000000 0b00001000
	0b10000000 0b00010000
	0b10000000 0b01100000
	0b11111111 0b10000000
	0b11000000 0b00000000
	0b10100000 0b00000000
	0b10010000 0b00000000
	0b10001000 0b00000000
	0b10000100 0b00000000
	0b10000010 0b00000000
	0b10000001 0b00000000
	0b10000000 0b10000000
	0b10000000 0b01000000
	0b10000000 0b00100000
	0b10000000 0b00010000
	0b10000000 0b00001000
	0b10000000 0b00000100
	0b10000000 0b00000010

	0b00000111 0b11000000
	0b00011000 0b00110000
	0b00100000 0b00001000
	0b01000000 0b00000100
	0b01000000 0b00000100
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b01000000 0b00000100
	0b01000000 0b00000100
	0b00100000 0b00001000
	0b00011000 0b00110000
	0b00000111 0b11000000

	0b00000011 0b11111110
	0b00001100 0b00000000
	0b00010000 0b00000000
	0b00100000 0b00000000
	0b01000000 0b00000000
	0b01000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b10000000 0b00000000
	0b01000000 0b00000000
	0b01000000 0b00000000
	0b00100000 0b00000000
	0b00010000 0b00000000
	0b00001100 0b00000000
	0b00000011 0b11111110

	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000100
	0b10000000 0b00001000
	0b10000000 0b00010000
	0b10000000 0b00100000
	0b10000000 0b01000000
	0b10000000 0b10000000
	0b10000001 0b10000000
	0b10000001 0b00000000
	0b10000010 0b00000000
	0b10000100 0b00000000
	0b10001000 0b00000000
	0b10010000 0b00000000
	0b10100000 0b00000000
	0b11000000 0b00000000
	0b11000000 0b00000000
	0b10100000 0b00000000
	0b10010000 0b00000000
	0b10001000 0b00000000
	0b10000100 0b00000000
	0b10000010 0b00000000
	0b10000001 0b00000000
	0b10000001 0b10000000
	0b10000000 0b10000000
	0b10000000 0b01000000
	0b10000000 0b00100000
	0b10000000 0b00010000
	0b10000000 0b00001000
	0b10000000 0b00000100
	0b10000000 0b00000010
	0b10000000 0b00000010

	0b11111111 0b11111110
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000
	0b00000001 0b00000000

	0b00000111 0b11000000
	0b00011000 0b00110000
	0b00100000 0b00001000
	0b01000000 0b00000100
	0b01000000 0b00000100
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b10000000 0b00000010
	0b01000000 0b00000100
	0b01000000 0b00000100
	0b00100000 0b00001000
	0b00011000 0b00110000
	0b00000111 0b11000000

# consts

:const TILE_SIZE    8
:const LEVEL_WIDTH  16
:const LEVEL_HEIGHT 7
:const LEVEL_SIZE   112
:const TITLE_WIDTH  112
:const TITLE_HEIGHT 32

:const MOVE_LEFT  7
:const MOVE_RIGHT 9
:const MOVE_UP    5
:const MOVE_DOWN  8
:const MOVE_RESET 1

:const TILE_BLANK   0
:const TILE_WALL    1
:const TILE_DIRT    2
:const TILE_BOULDER 3
:const TILE_DIAMOND 4
:const TILE_PLAYER  5
:const TILE_EXIT    6

:const DEAD_NO    0
:const DEAD_YES   1
:const DEAD_RESET 2

# levels

: level0
	0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
	0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
	0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
	0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
	0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
	0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
	0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

: level1
	1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
	1 2 2 2 3 2 2 4 2 2 4 2 2 2 2 1
	1 1 1 1 3 2 2 4 2 2 3 2 2 2 2 1
	1 2 5 2 2 2 2 2 2 2 4 2 2 6 2 1
	1 2 2 2 0 2 2 0 2 2 2 2 1 1 1 1
	1 2 2 2 0 2 2 3 2 2 0 2 2 2 2 1
	1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

: level2
	1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
	1 3 3 3 1 2 2 2 2 2 2 1 4 4 4 1
	1 2 2 2 1 2 3 3 3 3 2 1 2 2 2 1
	1 5 2 2 2 2 2 4 4 3 2 2 2 2 6 1
	1 2 2 2 1 2 3 3 3 3 2 1 2 2 2 1
	1 4 4 4 1 2 1 1 1 1 2 1 3 3 3 1
	1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

: level3
	1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
	1 2 2 2 2 4 2 2 2 1 3 1 2 6 2 1
	1 2 2 2 1 3 1 2 2 1 4 1 2 2 2 1
	1 2 2 2 2 4 2 2 2 1 4 1 2 2 2 1
	1 2 2 2 1 3 1 2 2 1 4 1 2 2 2 1
	1 2 5 2 2 4 2 2 2 2 4 2 2 2 2 1
	1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

: level4
	1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
	1 2 2 2 2 0 1 4 1 0 2 2 2 2 2 1
	1 2 2 2 0 0 1 3 1 0 0 2 2 2 2 1
	1 2 2 0 0 0 1 3 1 0 0 0 2 2 2 1
	1 2 0 0 0 0 1 3 1 0 0 0 0 2 2 1
	1 5 0 0 0 0 0 3 0 0 0 0 0 0 6 1
	1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

: level5
	1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
	1 2 4 2 2 3 2 5 2 2 1 2 2 2 2 1
	1 4 2 2 2 2 2 2 2 2 3 0 0 0 4 1
	1 1 1 1 1 3 2 2 2 2 1 1 1 0 1 1
	1 4 2 2 2 3 2 2 2 2 1 2 2 0 3 1
	1 2 4 2 2 2 2 2 2 2 3 0 0 0 6 1
	1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

# vars

:alias tile     v0
:alias dir      v0
:alias x        v1
:alias y        v2
:alias z        v3
:alias draw-x   v4
:alias draw-y   v5
:alias move-x   v6
:alias move-y   v7
:alias player-x v8
:alias player-y v9
:alias diamonds va
:alias level-no vb
:alias dead     vc

# program

: start-level
	x := 0
	y := 0
	z := 0
	player-x := 0
	player-y := 0
	diamonds := 0
	dead := DEAD_NO
	clear
	loop
		i := level0
		move-x := 0
		move-y := LEVEL_SIZE
		loop
			i += move-y
			move-x += 1
			if move-x != level-no then
		again
		i += z
		load tile
		i := level0
		i += z
		save tile

		if tile == TILE_PLAYER  then jump start-level-player
		if tile == TILE_DIAMOND then jump start-level-diamond
		jump start-level-tile

		: start-level-player
		player-x := x
		player-y := y
		jump start-level-tile

		: start-level-diamond
		diamonds += 1
		
		: start-level-tile
		draw-tile
		x += 1
		if x == LEVEL_WIDTH then y += 1
		if x == LEVEL_WIDTH then x := 0
		z += 1
		if y != LEVEL_HEIGHT then
	again
	draw-hud
;

: draw-tile
	if tile == TILE_BLANK then ;
	i := sprite-wall
	tile += -1
	tile <<= tile
	tile <<= tile
	tile <<= tile
	i += tile

	draw-x := x
	draw-x <<= draw-x
	draw-x <<= draw-x
	draw-x <<= draw-x
	draw-y := y
	draw-y <<= draw-y
	draw-y <<= draw-y
	draw-y <<= draw-y
	sprite draw-x draw-y TILE_SIZE
;

: tile-address
	z := y
	z <<= z
	z <<= z
	z <<= z
	z <<= z
	z += x
;

: get-tile
	tile-address
	i := level0
	i += z
	load tile
;

: set-tile
	tile-address
	i := level0
	i += z
	save tile
;

: move-player
	loop
		x := player-x
		y := player-y
		move-x := 0
		move-y := 0

		dir := key
		if dir == MOVE_LEFT  then move-x := -1
		if dir == MOVE_RIGHT then move-x := 1
		if dir == MOVE_UP    then move-y := -1
		if dir == MOVE_DOWN  then move-y := 1
		if dir == MOVE_RESET then dead := DEAD_RESET
		if dead != DEAD_NO then ;

		tile := TILE_PLAYER
		draw-tile
		tile := TILE_BLANK
		set-tile

		x += move-x
		y += move-y		
		get-tile

		if tile == TILE_WALL    then jump move-player-blocked
		if tile == TILE_DIAMOND then jump move-player-diamond
		if tile == TILE_BOULDER then jump move-player-boulder
		if tile == TILE_EXIT    then jump move-player-exit
		jump move-player-draw
		
		: move-player-exit
		if diamonds == 0 then ;
		jump move-player-blocked

		: move-player-boulder
		if move-y != 0 then jump move-player-blocked
		x += move-x
		get-tile
		x -= move-x
		if tile != TILE_BLANK then jump move-player-blocked
		x += move-x
		draw-tile
		tile := TILE_BOULDER
		draw-tile
		tile := TILE_BOULDER
		set-tile
		x -= move-x
		jump move-player-draw
		
		: move-player-diamond
		draw-hud
		diamonds += -1
		draw-hud

		: move-player-draw
		draw-tile
		jump move-player-clear

		: move-player-blocked
		x -= move-x
		y -= move-y
		move-x := 0
		move-y := 0

		: move-player-clear
		tile := TILE_PLAYER
		set-tile
		draw-tile
		player-x := x
		player-y := y

		if move-x != 0 then jump move-player-gravity
		if move-y != 0 then jump move-player-gravity
		jump move-player-done
		: move-player-gravity
		x -= move-x
		y -= move-y
		apply-gravity
		x := player-x
		y := player-y
		x += 1
		y += 1
		apply-gravity
		x := player-x
		y := player-y
		x += -1
		y += 1
		apply-gravity
		if dead != DEAD_NO then ;
		: move-player-done
	again
;

: apply-gravity
	move-x := x
	move-y := y
	get-tile
	if tile != TILE_BLANK then ;
	: apply-gravity-start
	loop
		y += -1
		get-tile
		if tile == TILE_BOULDER then jump apply-gravity-object
		if tile == TILE_DIAMOND then jump apply-gravity-object
		jump apply-gravity-done

		: apply-gravity-object
		z := tile
		y += 1
		draw-tile

		if x != player-x then jump apply-gravity-safe
		if y != player-y then jump apply-gravity-safe
		dead := DEAD_YES

		: apply-gravity-safe
		tile := z
		set-tile
		y += -1
		draw-tile
		tile := TILE_BLANK
		set-tile
		
		if dead != DEAD_NO then ;
	again
	: apply-gravity-done
	move-y += 1
	x := move-x
	y := move-y
	get-tile
	if tile == TILE_BLANK  then jump apply-gravity-start
	if tile == TILE_PLAYER then jump apply-gravity-start
;

: draw-hud
	draw-x := 17
	draw-y := 57
	i := hex level-no
	sprite draw-x draw-y 5
	draw-x := 96
	draw-y := 56
	i := sprite-diamond
	sprite draw-x draw-y TILE_SIZE
	draw-x := 105
	draw-y := 57
	i := hex diamonds
	sprite draw-x draw-y 5
;

: draw-title
	draw-x := 16
	draw-y := 16
	dir := 32
	i := sprite-title
	loop
		sprite draw-x draw-y 0
		i += dir
		draw-y += 16
		if draw-y > TITLE_HEIGHT then draw-x += 16
		if draw-y > TITLE_HEIGHT then draw-y := 16
		if draw-x != TITLE_WIDTH then
	again
	dir := key
;

: main
	hires
	level-no := 1
	draw-title
	loop
		start-level
		move-player
		if dead == DEAD_NO then level-no += 1
		z := 10
		buzzer := z
		if dead != DEAD_RESET then dir := key		
	again